/*
 * useSSE - SSE通信组合式函数
 * 负责与后端 /api/sse/connect 建立连接并监听事件
 */

import { SSE_CONNECT_PATH } from '../utils/constants';

/**
 * 建立SSE连接并提供事件监听接口
 * @returns {{ connect: Function, close: Function, on: Function, connectionId: string|null, retry: Function }}
 */
export function useSSE() {
  let eventSource = null;
  let listeners = new Map();
  let connectionId = null;
  let retryCount = 0;
  const maxRetries = 3;
  const retryDelay = 2000; // 2秒

  /**
   * 触发事件回调
   * @param {string} type - 事件类型
   * @param {any} payload - 事件数据
   */
  function emit(type, payload) {
    const cbs = listeners.get(type) || [];
    cbs.forEach(cb => {
      try { cb(payload); } catch (e) { /* noop */ }
    });
  }

  /**
   * 注册事件监听
   * @param {string} type - 事件类型
   * @param {Function} cb - 回调函数
   */
  function on(type, cb) {
    const cbs = listeners.get(type) || [];
    cbs.push(cb);
    listeners.set(type, cbs);
    return () => {
      listeners.set(type, (listeners.get(type) || []).filter(fn => fn !== cb));
    };
  }

  /**
   * 建立SSE连接
   * @param {boolean} isRetry - 是否为重试连接
   * @returns {Promise<string>} 连接ID
   */
  async function connect(isRetry = false) {
    if (eventSource && !isRetry) return connectionId;
    
    // 如果是重试，先关闭旧连接
    if (isRetry && eventSource) {
      eventSource.close();
      eventSource = null;
    }
    
    eventSource = new EventSource(SSE_CONNECT_PATH);

    eventSource.addEventListener('connected', (e) => {
      try {
        const data = JSON.parse(e.data);
        connectionId = data.connectionId || null;
        retryCount = 0; // 重置重试计数
        emit('connected', data);
      } catch (_) {}
    });

    const forward = ['message','status','error','heartbeat','tool_call_start','tool_call_result','text_chunk'];
    forward.forEach(type => {
      eventSource.addEventListener(type, (e) => {
        try {
          emit(type, JSON.parse(e.data));
        } catch (_) {
          emit(type, e.data);
        }
      });
    });

    eventSource.onerror = (err) => {
      let errorDetail = {
        error: 'SSE连接错误',
        detail: err,
        readyState: eventSource ? eventSource.readyState : 'unknown',
        url: SSE_CONNECT_PATH,
        timestamp: new Date().toISOString(),
        retryCount,
        maxRetries
      };
      
      // 根据readyState提供更详细的错误信息
      if (eventSource) {
        switch (eventSource.readyState) {
          case EventSource.CONNECTING:
            errorDetail.message = '正在尝试连接到服务器...';
            break;
          case EventSource.OPEN:
            errorDetail.message = '连接已建立但发生错误';
            break;
          case EventSource.CLOSED:
            errorDetail.message = '连接已关闭';
            // 如果连接关闭且未超过重试次数，尝试重连
            if (retryCount < maxRetries) {
              setTimeout(() => {
                retryCount++;
                connect(true);
              }, retryDelay);
              return; // 不发送错误事件，等待重试
            } else {
              errorDetail.message = `连接断开，已达到最大重试次数 (${maxRetries})`;
            }
            break;
          default:
            errorDetail.message = '未知连接状态';
        }
      }
      
      emit('error', errorDetail);
    };

    return new Promise((resolve, reject) => {
      const off = on('connected', (data) => {
        off();
        resolve(connectionId);
      });
      
      // 设置连接超时
      setTimeout(() => {
        if (!connectionId) {
          off();
          reject(new Error('连接超时'));
        }
      }, 10000); // 10秒超时
    });
  }

  /**
   * 手动重试连接
   */
  function retry() {
    retryCount = 0; // 重置重试计数
    return connect(true);
  }

  /**
   * 中断当前SSE连接
   */
  function abort() {
    retryCount = maxRetries; // 阻止自动重试
    if (eventSource) {
      eventSource.close();
      eventSource = null;
      connectionId = null;
      emit('aborted', { message: '连接已中断' });
    }
  }

  /**
   * 关闭SSE连接
   */
  function close() {
    retryCount = maxRetries; // 阻止自动重试
    if (eventSource) {
      eventSource.close();
      eventSource = null;
      connectionId = null;
      listeners.clear();
    }
  }

  return { connect, close, on, abort, retry, get connectionId() { return connectionId; } };
}